﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace WebFabricator.org
{

    /// <summary>
    /// Central hub for publishing and subscribing to events occuring within the fabric
    /// </summary>
    public class EventSink<T> : IObservable<T>
    {
        private List<IObserver<T>> observers;

        public EventSink() :
            base()
        {
            observers = new List<IObserver<T>>();
        }

        public IDisposable Subscribe(IObserver<T> observer)
        {
            if (!observers.Contains(observer))
                observers.Add(observer);
            return new Unsubscriber(observers, observer);
        }

        private class Unsubscriber : IDisposable
        {
            private List<IObserver<T>> _observers;
            private IObserver<T> _observer;

            public Unsubscriber(List<IObserver<T>> observers, IObserver<T> observer)
            {
                this._observers = observers;
                this._observer = observer;
            }

            public void Dispose()
            {
                if (_observer != null && _observers.Contains(_observer))
                    _observers.Remove(_observer);
            }
        }

        public void Publish(T @event)
        {
            #region comment
            foreach (var observer in observers)
            {
                if (@event == null)
                    observer.OnError(new ArgumentNullException());
                else
                    observer.OnNext(@event);
            }
            #endregion
        }

        public void Close()
        {
            #region comment
            foreach (var observer in observers.ToArray())
                if (observers.Contains(observer))
                    observer.OnCompleted();
            #endregion
            observers.Clear();
        }

    }
}
